home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / samba.idb / usr / samba / src / source / locking_shm.c.z / locking_shm.c
Encoding:
C/C++ Source or Header  |  1998-10-28  |  21.2 KB  |  699 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    shared memory locking implementation
  5.    Copyright (C) Andrew Tridgell 1992-1998
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.    Revision History:
  22.  
  23.    12 aug 96: Erik.Devriendt@te6.siemens.be
  24.    added support for shared memory implementation of share mode locking
  25.  
  26.    May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
  27.    locking to deal with multiple share modes per open file.
  28.  
  29.    September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
  30.    support.
  31.  
  32.    October 1997 - split into separate file (tridge)
  33. */
  34.  
  35. #ifdef FAST_SHARE_MODES
  36.  
  37. #include "includes.h"
  38. extern int DEBUGLEVEL;
  39. extern connection_struct Connections[];
  40. extern files_struct Files[];
  41.  
  42. static struct shmem_ops *shmops;
  43.  
  44. /* share mode record pointed to in shared memory hash bucket */
  45. typedef struct
  46. {
  47.   int next_offset; /* offset of next record in chain from hash bucket */
  48.   int locking_version;
  49.   int32 st_dev;
  50.   int32 st_ino;
  51.   int num_share_mode_entries;
  52.   int share_mode_entries; /* Chain of share mode entries for this file */
  53.   char file_name[1];
  54. } share_mode_record;
  55.  
  56. /* share mode entry pointed to by share_mode_record struct */
  57. typedef struct
  58. {
  59.     int next_share_mode_entry;
  60.     share_mode_entry e;
  61. } shm_share_mode_entry;
  62.  
  63. static int read_only;
  64.  
  65.  
  66. /* Conversion to hash entry index from device and inode numbers. */
  67. #define HASH_ENTRY(dev,ino) ((((uint32)(dev)) ^ ((uint32)(ino))) % shmops->hash_size())
  68.  
  69.  
  70. /*******************************************************************
  71.   deinitialize the shared memory for share_mode management 
  72.   ******************************************************************/
  73. static BOOL shm_stop_share_mode_mgmt(void)
  74. {
  75.    return shmops->shm_close();
  76. }
  77.  
  78. /*******************************************************************
  79.   lock a hash bucket entry in shared memory for share_mode management 
  80.   ******************************************************************/
  81. static BOOL shm_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
  82. {
  83.   return shmops->lock_hash_entry(HASH_ENTRY(dev, inode));
  84. }
  85.  
  86. /*******************************************************************
  87.   unlock a hash bucket entry in shared memory for share_mode management 
  88.   ******************************************************************/
  89. static BOOL shm_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
  90. {
  91.   return shmops->unlock_hash_entry(HASH_ENTRY(dev, inode));
  92. }
  93.  
  94. /*******************************************************************
  95. get all share mode entries in shared memory for a dev/inode pair.
  96. ********************************************************************/
  97. static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, 
  98.                    share_mode_entry **old_shares)
  99. {
  100.   int *mode_array;
  101.   unsigned int hash_entry = HASH_ENTRY(dev, inode); 
  102.   share_mode_record *file_scanner_p;
  103.   share_mode_record *file_prev_p;
  104.   shm_share_mode_entry *entry_scanner_p;
  105.   shm_share_mode_entry *entry_prev_p;
  106.   int num_entries;
  107.   int num_entries_copied;
  108.   BOOL found = False;
  109.   share_mode_entry *share_array = (share_mode_entry *)0;
  110.  
  111.   *old_shares = 0;
  112.  
  113.   mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
  114.   
  115.   if(mode_array[hash_entry] == 0)
  116.   {
  117.     DEBUG(5,("get_share_modes hash bucket %d empty\n", hash_entry));
  118.     return 0;
  119.   }
  120.  
  121.   file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
  122.   file_prev_p = file_scanner_p;
  123.   while(file_scanner_p)
  124.   {
  125.     if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
  126.     {
  127.       found = True;
  128.       break;
  129.     }
  130.     else
  131.     {
  132.       file_prev_p = file_scanner_p ;
  133.       file_scanner_p = (share_mode_record *)shmops->offset2addr(
  134.                                     file_scanner_p->next_offset);
  135.     }
  136.   }
  137.   
  138.   if(!found)
  139.   {
  140.     DEBUG(5,("get_share_modes no entry for file dev = %d ino = %d\n",
  141.          dev, inode));
  142.     return (0);
  143.   }
  144.   
  145.   if(file_scanner_p->locking_version != LOCKING_VERSION)
  146.   {
  147.     DEBUG(0,("ERROR: get_share_modes  Deleting old share mode v1 %d dev=%d ino=%d\n", 
  148.          file_scanner_p->locking_version, dev, inode));
  149.     if(file_prev_p == file_scanner_p)
  150.       mode_array[hash_entry] = file_scanner_p->next_offset;
  151.     else
  152.       file_prev_p->next_offset = file_scanner_p->next_offset;
  153.     shmops->shm_free(shmops->addr2offset(file_scanner_p));
  154.     return (0);
  155.   }
  156.  
  157.   /* Allocate the old_shares array */
  158.   num_entries = file_scanner_p->num_share_mode_entries;
  159.   if(num_entries)
  160.   {
  161.     *old_shares = share_array = (share_mode_entry *)
  162.                  malloc(num_entries * sizeof(share_mode_entry));
  163.     if(*old_shares == 0)
  164.     {
  165.       DEBUG(0,("get_share_modes: malloc fail!\n"));
  166.       return 0;
  167.     }
  168.   }
  169.  
  170.   num_entries_copied = 0;
  171.   
  172.   entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
  173.                                            file_scanner_p->share_mode_entries);
  174.   entry_prev_p = entry_scanner_p;
  175.   while(entry_scanner_p)
  176.   {
  177.     int pid = entry_scanner_p->e.pid;
  178.  
  179.     if (pid && !process_exists(pid))
  180.     {
  181.       /* Delete this share mode entry */
  182.       shm_share_mode_entry *delete_entry_p = entry_scanner_p;
  183.  
  184.       if(entry_prev_p == entry_scanner_p)
  185.       {
  186.         /* We are at start of list */
  187.         file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
  188.         entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
  189.                                            file_scanner_p->share_mode_entries);
  190.         entry_prev_p = entry_scanner_p;
  191.       }
  192.       else
  193.       {
  194.         entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
  195.         entry_scanner_p = (shm_share_mode_entry*)
  196.                            shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
  197.       }
  198.       /* Decrement the number of share mode entries on this share mode record */
  199.       file_scanner_p->num_share_mode_entries -= 1;
  200.  
  201.       /* PARANOIA TEST */
  202.       if(file_scanner_p->num_share_mode_entries < 0)
  203.       {
  204.         DEBUG(0,("PANIC ERROR: get_share_mode: entries=%d dev=%d ino=%d\n",
  205.          file_scanner_p->num_share_mode_entries,dev, inode));
  206.         return 0;
  207.       }
  208.  
  209.       DEBUG(0,("get_share_modes: process %d no longer exists\n", pid));
  210.  
  211.       shmops->shm_free(shmops->addr2offset(delete_entry_p));
  212.     } 
  213.     else
  214.     {
  215.        /* This is a valid share mode entry and the process that
  216.            created it still exists. Copy it into the output array.
  217.        */
  218.        share_array[num_entries_copied].pid = entry_scanner_p->e.pid;
  219.        share_array[num_entries_copied].share_mode = entry_scanner_p->e.share_mode;
  220.        share_array[num_entries_copied].op_port = entry_scanner_p->e.op_port;
  221.        share_array[num_entries_copied].op_type = entry_scanner_p->e.op_type;
  222.        memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->e.time,
  223.               sizeof(struct timeval));
  224.        num_entries_copied++;
  225.        DEBUG(5,("get_share_modes Read share mode 0x%X pid=%d\n", 
  226.         entry_scanner_p->e.share_mode, entry_scanner_p->e.pid));
  227.        entry_prev_p = entry_scanner_p;
  228.        entry_scanner_p = (shm_share_mode_entry *)
  229.                            shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
  230.     }
  231.   }
  232.   
  233.   /* If no valid share mode entries were found then this record shouldn't exist ! */
  234.   if(num_entries_copied == 0)
  235.   {
  236.     DEBUG(0,("get_share_modes: file with dev %d inode %d empty\n", 
  237.          dev, inode));
  238.     if(*old_shares)
  239.       free((char *)*old_shares);
  240.     *old_shares = 0;
  241.  
  242.     if(file_prev_p == file_scanner_p)
  243.       mode_array[hash_entry] = file_scanner_p->next_offset;
  244.     else
  245.       file_prev_p->next_offset = file_scanner_p->next_offset;
  246.     shmops->shm_free(shmops->addr2offset(file_scanner_p));
  247.   }
  248.  
  249.   DEBUG(5,("get_share_modes: file with dev %d inode %d -> %d entries\n",
  250.        dev, inode, num_entries_copied));
  251.  
  252.   return(num_entries_copied);
  253. }  
  254.  
  255. /*******************************************************************
  256. del the share mode of a file.
  257. ********************************************************************/
  258. static void shm_del_share_mode(int token, int fnum)
  259. {
  260.   uint32 dev, inode;
  261.   int *mode_array;
  262.   unsigned int hash_entry;
  263.   share_mode_record *file_scanner_p;
  264.   share_mode_record *file_prev_p;
  265.   shm_share_mode_entry *entry_scanner_p;
  266.   shm_share_mode_entry *entry_prev_p;
  267.   BOOL found = False;
  268.   int pid = getpid();
  269.  
  270.   dev = Files[fnum].fd_ptr->dev;
  271.   inode = Files[fnum].fd_ptr->inode;
  272.  
  273.   hash_entry = HASH_ENTRY(dev, inode);
  274.  
  275.   mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
  276.  
  277.   if(mode_array[hash_entry] == 0)
  278.   {  
  279.     DEBUG(0,("PANIC ERROR:del_share_mode hash bucket %d empty\n", 
  280.                   hash_entry));
  281.     return;
  282.   }  
  283.   
  284.   file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
  285.   file_prev_p = file_scanner_p;
  286.  
  287.   while(file_scanner_p)
  288.   {
  289.     if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
  290.     {
  291.       found = True;
  292.       break;
  293.     }
  294.     else
  295.     {
  296.       file_prev_p = file_scanner_p ;
  297.       file_scanner_p = (share_mode_record *)
  298.                         shmops->offset2addr(file_scanner_p->next_offset);
  299.     }
  300.   }
  301.     
  302.   if(!found)
  303.   {
  304.      DEBUG(0,("ERROR: del_share_mode no entry for dev %d inode %d\n",
  305.           dev, inode));
  306.      return;
  307.   }
  308.   
  309.   if(file_scanner_p->locking_version != LOCKING_VERSION)
  310.   {
  311.     DEBUG(0,("ERROR: del_share_modes Deleting old share mode v1 %d dev=%d ino=%d\n",
  312.          file_scanner_p->locking_version, dev, inode));
  313.     if(file_prev_p == file_scanner_p)
  314.       mode_array[hash_entry] = file_scanner_p->next_offset;
  315.     else
  316.       file_prev_p->next_offset = file_scanner_p->next_offset;
  317.     shmops->shm_free(shmops->addr2offset(file_scanner_p));
  318.     return;
  319.   }
  320.  
  321.   found = False;
  322.   entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
  323.                                          file_scanner_p->share_mode_entries);
  324.   entry_prev_p = entry_scanner_p;
  325.   while(entry_scanner_p)
  326.   {
  327.     if( (pid == entry_scanner_p->e.pid) && 
  328.           (memcmp(&entry_scanner_p->e.time, 
  329.                  &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
  330.     {
  331.       found = True;
  332.       break;
  333.     }
  334.     else
  335.     {
  336.       entry_prev_p = entry_scanner_p;
  337.       entry_scanner_p = (shm_share_mode_entry *)
  338.                           shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
  339.     }
  340.   } 
  341.  
  342.   if (found)
  343.   {
  344.     /* Decrement the number of entries in the record. */
  345.     file_scanner_p->num_share_mode_entries -= 1;
  346.  
  347.     DEBUG(2,("del_share_modes Deleting share mode entry dev=%d ino=%d\n",
  348.               dev, inode));
  349.     if(entry_prev_p == entry_scanner_p)
  350.       /* We are at start of list */
  351.       file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
  352.     else
  353.       entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
  354.     shmops->shm_free(shmops->addr2offset(entry_scanner_p));
  355.  
  356.     /* PARANOIA TEST */
  357.     if(file_scanner_p->num_share_mode_entries < 0)
  358.     {
  359.       DEBUG(0,("PANIC ERROR:del_share_mode num_share_mode_entries=%d\n", 
  360.            file_scanner_p->num_share_mode_entries));
  361.       return;
  362.     }
  363.  
  364.     /* If we deleted the last share mode entry then remove the share mode record. */
  365.     if(file_scanner_p->num_share_mode_entries == 0)
  366.     {
  367.       DEBUG(2,("del_share_modes num entries = 0, deleting share_mode dev=%d ino=%d\n", 
  368.            dev, inode));
  369.       if(file_prev_p == file_scanner_p)
  370.         mode_array[hash_entry] = file_scanner_p->next_offset;
  371.       else
  372.         file_prev_p->next_offset = file_scanner_p->next_offset;
  373.       shmops->shm_free(shmops->addr2offset(file_scanner_p));
  374.     }
  375.   }
  376.   else
  377.   {
  378.     DEBUG(0,("ERROR: del_share_modes No share mode dev=%d ino=%d\n", 
  379.          dev, inode));
  380.   }
  381. }
  382.  
  383. /*******************************************************************
  384. set the share mode of a file. Return False on fail, True on success.
  385. ********************************************************************/
  386. static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type)
  387. {
  388.   files_struct *fs_p = &Files[fnum];
  389.   int32 dev, inode;
  390.   int *mode_array;
  391.   unsigned int hash_entry;
  392.   share_mode_record *file_scanner_p;
  393.   share_mode_record *file_prev_p;
  394.   shm_share_mode_entry *new_entry_p;
  395.   int new_entry_offset;
  396.   BOOL found = False;
  397.  
  398.   dev = fs_p->fd_ptr->dev;
  399.   inode = fs_p->fd_ptr->inode;
  400.  
  401.   hash_entry = HASH_ENTRY(dev, inode);
  402.  
  403.   mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
  404.  
  405.   file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
  406.   file_prev_p = file_scanner_p;
  407.   
  408.   while(file_scanner_p)
  409.   {
  410.     if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
  411.     {
  412.       found = True;
  413.       break;
  414.     }
  415.     else
  416.     {
  417.       file_prev_p = file_scanner_p ;
  418.       file_scanner_p = (share_mode_record *)
  419.                          shmops->offset2addr(file_scanner_p->next_offset);
  420.     }
  421.   }
  422.   
  423.   if(!found)
  424.   {
  425.     /* We must create a share_mode_record */
  426.     share_mode_record *new_mode_p = NULL;
  427.     int new_offset = shmops->shm_alloc(sizeof(share_mode_record) +
  428.                    strlen(fs_p->name) + 1);
  429.     if(new_offset == 0) {
  430.         DEBUG(0,("ERROR:set_share_mode shmops->shm_alloc fail!\n"));
  431.         return False;
  432.     }
  433.     new_mode_p = shmops->offset2addr(new_offset);
  434.     new_mode_p->locking_version = LOCKING_VERSION;
  435.     new_mode_p->st_dev = dev;
  436.     new_mode_p->st_ino = inode;
  437.     new_mode_p->num_share_mode_entries = 0;
  438.     new_mode_p->share_mode_entries = 0;
  439.     pstrcpy(new_mode_p->file_name, fs_p->name);
  440.  
  441.     /* Chain onto the start of the hash chain (in the hope we will be used first). */
  442.     new_mode_p->next_offset = mode_array[hash_entry];
  443.     mode_array[hash_entry] = new_offset;
  444.  
  445.     file_scanner_p = new_mode_p;
  446.  
  447.     DEBUG(3,("set_share_mode: Created share record for %s (dev %d inode %d)\n", 
  448.          fs_p->name, dev, inode));
  449.   }
  450.  
  451.   /* Now create the share mode entry */ 
  452.   new_entry_offset = shmops->shm_alloc(sizeof(shm_share_mode_entry));
  453.   if(new_entry_offset == 0) {
  454.       int delete_offset = mode_array[hash_entry];
  455.       DEBUG(0,("ERROR:set_share_mode: shmops->shm_alloc fail 1!\n"));
  456.       /* Unlink the damaged record */
  457.       mode_array[hash_entry] = file_scanner_p->next_offset;
  458.       /* And delete it */
  459.       shmops->shm_free( delete_offset );
  460.       return False;
  461.   }
  462.  
  463.   new_entry_p = shmops->offset2addr(new_entry_offset);
  464.  
  465.   new_entry_p->e.pid = getpid();
  466.   new_entry_p->e.share_mode = fs_p->share_mode;
  467.   new_entry_p->e.op_port = port;
  468.   new_entry_p->e.op_type = op_type;
  469.   memcpy( (char *)&new_entry_p->e.time, (char *)&fs_p->open_time, sizeof(struct timeval));
  470.  
  471.   /* Chain onto the share_mode_record */
  472.   new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries;
  473.   file_scanner_p->share_mode_entries = new_entry_offset;
  474.  
  475.   /* PARANOIA TEST */
  476.   if(file_scanner_p->num_share_mode_entries < 0)
  477.   {
  478.     DEBUG(0,("PANIC ERROR:set_share_mode num_share_mode_entries=%d\n", 
  479.          file_scanner_p->num_share_mode_entries));
  480.     return False;
  481.   }
  482.  
  483.   /* Increment the share_mode_entries counter */
  484.   file_scanner_p->num_share_mode_entries += 1;
  485.  
  486.   DEBUG(3,("set_share_mode: Created share entry for %s with mode 0x%X pid=%d\n",
  487.        fs_p->name, fs_p->share_mode, new_entry_p->e.pid));
  488.  
  489.   return(True);
  490. }
  491.  
  492. /*******************************************************************
  493. Remove an oplock port and mode entry from a share mode.
  494. ********************************************************************/
  495. static BOOL shm_remove_share_oplock(int fnum, int token)
  496. {
  497.   uint32 dev, inode;
  498.   int *mode_array;
  499.   unsigned int hash_entry;
  500.   share_mode_record *file_scanner_p;
  501.   share_mode_record *file_prev_p;
  502.   shm_share_mode_entry *entry_scanner_p;
  503.   shm_share_mode_entry *entry_prev_p;
  504.   BOOL found = False;
  505.   int pid = getpid();
  506.  
  507.   dev = Files[fnum].fd_ptr->dev;
  508.   inode = Files[fnum].fd_ptr->inode;
  509.  
  510.   hash_entry = HASH_ENTRY(dev, inode);
  511.  
  512.   mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
  513.  
  514.   if(mode_array[hash_entry] == 0)
  515.   {
  516.     DEBUG(0,("PANIC ERROR:remove_share_oplock: hash bucket %d empty\n",
  517.                   hash_entry));
  518.     return False;
  519.   } 
  520.     
  521.   file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
  522.   file_prev_p = file_scanner_p;
  523.     
  524.   while(file_scanner_p)
  525.   { 
  526.     if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
  527.     {
  528.       found = True;
  529.       break;
  530.     }
  531.     else
  532.     {
  533.       file_prev_p = file_scanner_p ;
  534.       file_scanner_p = (share_mode_record *)
  535.                         shmops->offset2addr(file_scanner_p->next_offset);
  536.     }
  537.   } 
  538.    
  539.   if(!found)
  540.   { 
  541.      DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%d ino=%d\n", 
  542.           dev, inode));
  543.      return False;
  544.   } 
  545.  
  546.   if(file_scanner_p->locking_version != LOCKING_VERSION)
  547.   {
  548.     DEBUG(0,("ERROR: remove_share_oplock: Deleting old share mode v1=%d dev=%d ino=%d\n",
  549.          file_scanner_p->locking_version, dev, inode));
  550.     if(file_prev_p == file_scanner_p)
  551.       mode_array[hash_entry] = file_scanner_p->next_offset;
  552.     else
  553.       file_prev_p->next_offset = file_scanner_p->next_offset;
  554.     shmops->shm_free(shmops->addr2offset(file_scanner_p));
  555.     return False;
  556.   }
  557.  
  558.   found = False;
  559.   entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
  560.                                          file_scanner_p->share_mode_entries);
  561.   entry_prev_p = entry_scanner_p;
  562.   while(entry_scanner_p)
  563.   {
  564.     if( (pid == entry_scanner_p->e.pid) && 
  565.         (entry_scanner_p->e.share_mode == Files[fnum].share_mode) &&
  566.         (memcmp(&entry_scanner_p->e.time, 
  567.                 &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
  568.     {
  569.       /* Delete the oplock info. */
  570.       entry_scanner_p->e.op_port = 0;
  571.       entry_scanner_p->e.op_type = 0;
  572.       found = True;
  573.       break;
  574.     }
  575.     else
  576.     {
  577.       entry_prev_p = entry_scanner_p;
  578.       entry_scanner_p = (shm_share_mode_entry *)
  579.                           shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
  580.     }
  581.   } 
  582.  
  583.   if(!found)
  584.   {
  585.     DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%d ino=%d\n", 
  586.          dev, inode));
  587.     return False;
  588.   }
  589.  
  590.   return True;
  591. }
  592.  
  593.  
  594. /*******************************************************************
  595. call the specified function on each entry under management by the
  596. share mode system
  597. ********************************************************************/
  598. static int shm_share_forall(void (*fn)(share_mode_entry *, char *))
  599. {
  600.     int i, count=0;
  601.     int *mode_array;
  602.     share_mode_record *file_scanner_p;
  603.  
  604.     mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
  605.  
  606.     for( i = 0; i < shmops->hash_size(); i++) {
  607.         shmops->lock_hash_entry(i);
  608.         if(mode_array[i] == 0)  {
  609.             shmops->unlock_hash_entry(i);
  610.             continue;
  611.         }
  612.  
  613.         file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[i]);
  614.         while((file_scanner_p != 0) && 
  615.               (file_scanner_p->num_share_mode_entries != 0)) {
  616.             shm_share_mode_entry *entry_scanner_p = 
  617.                 (shm_share_mode_entry *)
  618.                 shmops->offset2addr(file_scanner_p->share_mode_entries);
  619.  
  620.             while(entry_scanner_p != 0) {
  621.                 
  622.                 if (process_exists(entry_scanner_p->e.pid)) {
  623.                     fn(&entry_scanner_p->e, 
  624.                        file_scanner_p->file_name);
  625.                     count++;
  626.                 }
  627.  
  628.                 entry_scanner_p = 
  629.                     (shm_share_mode_entry *)
  630.                     shmops->offset2addr(
  631.                                 entry_scanner_p->next_share_mode_entry);
  632.             } /* end while entry_scanner_p */
  633.             file_scanner_p = (share_mode_record *)
  634.                 shmops->offset2addr(file_scanner_p->next_offset);
  635.         } /* end while file_scanner_p */
  636.         shmops->unlock_hash_entry(i);
  637.     } /* end for */
  638.  
  639.     return count;
  640. }
  641.  
  642.  
  643. /*******************************************************************
  644. dump the state of the system
  645. ********************************************************************/
  646. static void shm_share_status(FILE *f)
  647. {
  648.     int bytes_free, bytes_used, bytes_overhead, bytes_total;
  649.  
  650.     shmops->get_usage(&bytes_free, &bytes_used, &bytes_overhead);
  651.     bytes_total = bytes_free + bytes_used + bytes_overhead;
  652.  
  653.     fprintf(f, "Share mode memory usage (bytes):\n");
  654.     fprintf(f, "   %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total\n",
  655.         bytes_free, (bytes_free * 100)/bytes_total,
  656.         bytes_used, (bytes_used * 100)/bytes_total,
  657.         bytes_overhead, (bytes_overhead * 100)/bytes_total,
  658.         bytes_total);
  659. }
  660.  
  661.  
  662. static struct share_ops share_ops = {
  663.     shm_stop_share_mode_mgmt,
  664.     shm_lock_share_entry,
  665.     shm_unlock_share_entry,
  666.     shm_get_share_modes,
  667.     shm_del_share_mode,
  668.     shm_set_share_mode,
  669.     shm_remove_share_oplock,
  670.     shm_share_forall,
  671.     shm_share_status,
  672. };
  673.  
  674. /*******************************************************************
  675.   initialize the shared memory for share_mode management 
  676.   ******************************************************************/
  677. struct share_ops *locking_shm_init(int ronly)
  678. {
  679.     read_only = ronly;
  680.  
  681. #ifdef USE_SYSV_IPC
  682.     shmops = sysv_shm_open(read_only);
  683.     if (shmops) return &share_ops;
  684. #endif
  685.  
  686.     shmops = smb_shm_open(read_only);
  687.     if (shmops) return &share_ops;
  688.  
  689.     return NULL;
  690. }
  691.  
  692. #else
  693.  int locking_shm_dummy_procedure(void)
  694. {return 0;}
  695. #endif
  696.  
  697.  
  698.  
  699.